package com.ken.common.sentinel.applicaiton;

import com.alibaba.csp.sentinel.cluster.ClusterStateManager;
import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientAssignConfig;
import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfig;
import com.alibaba.csp.sentinel.cluster.client.config.ClusterClientConfigManager;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.ken.common.sentinel.config.SentinelNacosProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;

import java.util.List;

/**
 * Sentinel集群流控客户端配置类
 */
public class SentinelClusterClientConfiguration implements CommandLineRunner {

    /**
     * 注入配置信息
     */
    @Autowired
    private SentinelNacosProperties sentinelNacosProperties;

    @Value("${spring.application.name}")
    private String appName;

    @Override
    public void run(String... args) throws Exception {
        System.out.println("Sentinel客户端初始化！！！！");
        /**
         * 配置当前模式为客户端
         */
        ClusterStateManager.applyState(ClusterStateManager.CLUSTER_CLIENT);
        //配置服务端地址
        // 初始化一个配置ClusterClientConfig的 Nacos 数据源
        ReadableDataSource<String, ClusterClientAssignConfig> ds =
                new NacosDataSource<>(sentinelNacosProperties.getServerProperties(),
                        sentinelNacosProperties.getGroupId(),
                        sentinelNacosProperties.getClientConfigDataId(),
                        source -> JSON.parseObject(source, new TypeReference<ClusterClientAssignConfig>() {}));
        ClusterClientConfigManager.registerServerAssignProperty(ds.getProperty());

        //配置客户端相关配置
        ReadableDataSource<String, ClusterClientConfig> ds2 =
                new NacosDataSource<>(sentinelNacosProperties.getServerProperties(),
                        sentinelNacosProperties.getGroupId(),
                        sentinelNacosProperties.getClientConfigDataId(),
                        source -> JSON.parseObject(source, new TypeReference<ClusterClientConfig>() {}));
        ClusterClientConfigManager.registerClientConfigProperty(ds2.getProperty());

        //配置从Nacos上获取流控规则
        ReadableDataSource<String, List<FlowRule>> ds3 =
                new NacosDataSource<>(sentinelNacosProperties.getServerProperties(),
                        sentinelNacosProperties.getGroupId(),
                        appName + sentinelNacosProperties.getFlowRulePrefix(),
                        source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
        FlowRuleManager.register2Property(ds3.getProperty());

        //配置从Nacos上获取参数流控规则
        ReadableDataSource<String, List<ParamFlowRule>> ds4 =
                new NacosDataSource<>(sentinelNacosProperties.getServerProperties(),
                        sentinelNacosProperties.getGroupId(),
                        appName + sentinelNacosProperties.getFlowParamRulePrefix(),
                        source -> JSON.parseObject(source, new TypeReference<List<ParamFlowRule>>() {}));
        ParamFlowRuleManager.register2Property(ds4.getProperty());

        //配置从Nacos上获取熔断限流规则
        ReadableDataSource<String, List<DegradeRule>> ds5 =
                new NacosDataSource<>(sentinelNacosProperties.getServerProperties(),
                        sentinelNacosProperties.getGroupId(),
                        appName + sentinelNacosProperties.getDegradeRulePrefix(),
                        source -> JSON.parseObject(source, new TypeReference<List<DegradeRule>>() {}));
        DegradeRuleManager.register2Property(ds5.getProperty());
    }
}
